package org.springblade.modules.repair.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.repair.dto.PlanAbarbeitungSearchDTO;
import org.springblade.modules.repair.dto.PlanLogDTO;
import org.springblade.modules.repair.entity.*;
import org.springblade.modules.repair.enums.MaintainPlanContentEnum;
import org.springblade.modules.repair.enums.TaskStatusEnum;
import org.springblade.modules.repair.enums.WorkTrackStatusEnum;
import org.springblade.modules.repair.mapper.MaintainAbarbeitungDetailMapper;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.vo.*;
import org.springblade.modules.repair.vo.plan.v2.PlanUserSignDetailVo;
import org.springblade.modules.repair.vo.plan.wx.PlanMaintainUserVO;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@AllArgsConstructor
@Service
public class MaintainAbarbeitungServiceImpl extends BaseServiceImpl<MaintainAbarbeitungDetailMapper, MaintainAbarbeitungDetail> implements MaintainAbarbeitungService {

	private final IMaintainPlanContentService planContentService;
	private final IMaintainPlanContentExtService planContentExtService;
	private final IMaintainPlanContentUserService planContentUserService;
	private final IMaintainByScoreQuestionService byScoreQuestionService;
	private final IMaintainSignService signService;
	private final IMaintainMalfunctionLogService malfunctionLogService;
	private final MaintainAbarbeitungRecordService abarbeitungRecordService;
	private final IMaintainCheckHistoryService checkHistoryService;
	private final IUserService userService;

	@Override
	public IPage<PlanAbarbeitungPageVO> selectPage(PlanAbarbeitungSearchDTO searchDTO, IPage<PlanAbarbeitungPageVO> page) {
		return page.setRecords(baseMapper.selectPlanAbarbeitungPage(searchDTO,page));
	}

	@Override
	public Map<String, Object> selectPageCount() {
		return baseMapper.selectPageCount();
	}

	@Override
	public PlanAbarbeitungDetailVO selectDetail(Long planId) {
		PlanAbarbeitungDetailVO detailVO = baseMapper.selectDetail(planId);
		if(Func.isEmpty(detailVO)){
			throw new ServiceException("该整改工单不存在");
		}

		// 查询来源工单历史记录
		List<PlanAbarbeitungByContentVO> fromHistoryList = baseMapper.selectFromHistoryList(planId);
		detailVO.setFromHistoryList(fromHistoryList);

		List<PlanAbarbeitungByContentVO> afterHistoryList;
		if(detailVO.getPlanStatus().equals(TaskStatusEnum.ZG_ALLOCATION.getStatus()) || detailVO.getPlanStatus().equals(TaskStatusEnum.ZG_TO_START.getStatus())){
			afterHistoryList = baseMapper.selectAfterHistoryListByTemplateContent(planId);
		}else {
			afterHistoryList = baseMapper.selectAfterHistoryListByCheckHistory(planId);
		}
		detailVO.setAfterHistoryList(afterHistoryList);

		// 人员信息
		List<PlanMaintainUserVO> maintainUserList = planContentUserService.selectWorkUsers(planId);
		detailVO.setMaintainUserList(maintainUserList);

		// 查询该任务电梯最近一次完成的任务
		LastPlanVO lastPlanVO = planContentService.selectElevatorLastPlan(detailVO.getElevatorId(), planId);
		detailVO.setLastPlan(lastPlanVO);

		WorkTrackVO workTrack = malfunctionLogService.selectWorkTracks(planId);
		detailVO.setWorkTrack(workTrack);
		return detailVO;
	}

	@Override
	public List<MaintainAbarbeitungRecord> recordList(Long planId) {
		return abarbeitungRecordService.recordList(planId);
	}

	@Override
	public List<FromPlanVO> fromPlan(Long planId) {
		List<FromPlanVO> resultList = new ArrayList<>();
		List<MaintainByScoreQuestion> byScoreQuestions = byScoreQuestionService.list(Wrappers.<MaintainByScoreQuestion>lambdaQuery().eq(MaintainByScoreQuestion::getChildPlanId,planId));
		if(Func.isNotEmpty(byScoreQuestions)){
			List<Long> fromPlanIds = byScoreQuestions.stream().map(MaintainByScoreQuestion::getPlanId).distinct().collect(Collectors.toList());
			resultList = baseMapper.selectZgFromPlan(fromPlanIds);
			if(Func.isNotEmpty(resultList)){
				resultList.forEach(e -> {
					e.setPlanTypeStatusName(MaintainPlanContentEnum.getName(e.getPlanTypeStatus()));
					e.setPlanStatusName(TaskStatusEnum.getTaskName(e.getPlanTypeStatus(),e.getPlanStatus()));
				});
			}
		}
		return resultList;
	}

	@Override
	public void addHistory(Long planId) {

		List<PlanAbarbeitungByContentVO> afterHistoryList = baseMapper.selectAfterHistoryListByTemplateContent(planId);
		if(Func.isEmpty(afterHistoryList)){
			throw new ServiceException("找不到对应工作项,请联系管理员!");
		}

		// 创建整改工单的保养工作项历史记录
		List<MaintainCheckHistory> checkHistories = new ArrayList<>();
		afterHistoryList.forEach(e -> {
			MaintainCheckHistory checkHistory = new MaintainCheckHistory();
			checkHistory.setPlanId(e.getChildPlanId());
			checkHistory.setTemplateContentId(e.getTemplateContentId());
			if(e.getIsSign() == 1){
				checkHistory.setTemplateContentId(-1L);
			}
			checkHistory.setName(e.getName());
			checkHistory.setTltNames(e.getTltNames());
			checkHistory.setTltIds(e.getTltIds());
			checkHistory.setLocationType(e.getLocationType());
			checkHistory.setLocationTypeName(e.getLocationTypeName());
			checkHistory.setTemplateId(e.getTemplateId());
			checkHistory.setTemplateName(e.getTemplateName());
			checkHistory.setRequireDesc(e.getRequireDesc());
			checkHistory.setRequireImg(e.getRequireImg());
			checkHistory.setRecordData(e.getRecordData());
			checkHistory.setTenantId(AuthUtil.getTenantId());
			checkHistory.setByScoreQuestionId(e.getByScoreQuestionId());
			checkHistories.add(checkHistory);
		});
		checkHistoryService.saveBatch(checkHistories);

		// 冗余保养项历史记录进问题记录表
		List<MaintainByScoreQuestion> byScoreQuestions = new ArrayList<>();
		checkHistories.forEach(e -> {
			MaintainByScoreQuestion byScoreQuestion = new MaintainByScoreQuestion();
			byScoreQuestion.setId(e.getByScoreQuestionId());
			byScoreQuestion.setChildPlanCheckHistoryId(e.getId());
			byScoreQuestions.add(byScoreQuestion);
		});
		byScoreQuestionService.updateBatchById(byScoreQuestions);

	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Boolean finish(MaintainAbarbeitungDetail entity) {

		MaintainPlanContent planContent = planContentService.getById(entity.getPlanId());
		if(Func.isEmpty(planContent)){
			throw new ServiceException("该整改工单不存在");
		}
		if(planContent.getStatus() != TaskStatusEnum.ZG_UNDER_WAY.getStatus()){
			throw new ServiceException("工单状态已变更，请刷新页面");
		}

		// 处理未签退人员签退记录 统一系统代签
		List<MaintainSign> signList = signService.list(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId,entity.getPlanId()));

		if(Func.isNotEmpty(signList)){
			List<MaintainSign> notSignOut = signList.stream().filter(e -> Func.isEmpty(e.getSignOutTime())).collect(Collectors.toList());
			if(Func.isNotEmpty(notSignOut)){
				notSignOut.forEach(e -> {
					e.setSignOutTime(DateUtil.date());
					e.setSignOutStatus(1);
					e.setStatus(2);

					User user = userService.getById(e.getUserId());
					PlanLogDTO planLogDTO = new PlanLogDTO();
					planLogDTO.setSignId(e.getId());
					planLogDTO.setExpDesc(WorkTrackStatusEnum.SYSTEM_SIGN.getTypeName());
					malfunctionLogService.insertWorkLog(e.getPlanId(), WorkTrackStatusEnum.SIGN_OUT.getTypeName(), planContent.getStatus(), JSONObject.toJSONString(planLogDTO), AuthUtil.getUserId(), user.getRealName());
				});
				signService.updateBatchById(notSignOut);
			}

		}


		List<Long> signUser = signList.stream().map(MaintainSign::getUserId).distinct().collect(Collectors.toList());
		List<MaintainPlanContentUser> users = planContentUserService.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId,entity.getPlanId()));
		users = users.stream().filter(e -> !signUser.contains(e.getUserId())).collect(Collectors.toList());
		if(Func.isNotEmpty(users)){
			planContentUserService.removeByIds(users.stream().map(MaintainPlanContentUser::getId).collect(Collectors.toList()));
		}

		// 完成工单需要把所有的人工单头像亮--to--不亮
		List<MaintainPlanContentUser> planContentUserList = planContentUserService.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, entity.getPlanId()));
		for (MaintainPlanContentUser maintainPlanContentUser : planContentUserList) {
			PlanUserSignDetailVo userSign = maintainPlanContentUser.getSignUser();
			if (userSign != null) {
				userSign.setIsPlanStatus(false);
			}
			maintainPlanContentUser.setSignInfo(JSONObject.toJSONString(userSign));
		}
		planContentUserService.updateBatchById(planContentUserList);

		MaintainAbarbeitungDetail detail = super.getOne(Wrappers.<MaintainAbarbeitungDetail>lambdaQuery().eq(MaintainAbarbeitungDetail::getPlanId,entity.getPlanId()));
		MaintainPlanContentExt ext = planContentExtService.getOne(Wrappers.<MaintainPlanContentExt>lambdaQuery().eq(MaintainPlanContentExt::getPlanId,entity.getPlanId()));
		ext.setPlanEndTime(DateUtil.date());
		long timeInterval = signList.stream().filter(e -> !e.getStatus().equals(2)).mapToLong(e -> e.getSignOutTime().getTime() - e.getSignTime().getTime()).sum();
		ext.setWorkMill(timeInterval);
		ext.setWorkMinute(BigDecimal.valueOf(timeInterval).divide(BigDecimal.valueOf(60*1000),0, RoundingMode.HALF_UP).intValue());
		if(detail.getRedeployCount() > 0){
			detail.setRedeployOverdueStatus(1);
			if(Func.isNotEmpty(detail.getRedeployFinishDate())){
				if(detail.getRedeployFinishDate().getTime() < DateUtil.parseDate(DateUtil.today()).getTime()){
					detail.setRedeployOverdueStatus(3);
				}
			}
		}else {
			ext.setOverdueType(1);
			if(Func.isNotEmpty(planContent.getPlanFinishDate())){
				if(planContent.getPlanFinishDate().getTime() < DateUtil.parseDate(DateUtil.today()).getTime()){
					ext.setOverdueType(3);
				}
			}
		}

		super.updateById(detail);
		planContentExtService.updateById(ext);
		planContent.setStatus(TaskStatusEnum.ZG_SIGN_FINISH.getStatus());
		malfunctionLogService.insertWorkLog(entity.getPlanId(), WorkTrackStatusEnum.FINISHED.getTypeName(),TaskStatusEnum.ZG_SIGN_FINISH.getStatus());
		return planContentService.updateById(planContent);
	}

}
